<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
/* "display: none" prevents loading of <object> resources, so use */
/* "visibility: hidden" instead. */
.invisible { visibility: hidden; }
</style>
<script>
const urls = {
    '/resources/square20.jpg': ['img', 529],
    '/resources/square20.gif': ['img', 50],
    '/resources/square20.png': ['img', 150],
    '/resources/test.ogv': ['video', 103746],
    '/resources/test.oga': ['audio', 20787],
    '/resources/dummy.html': ['iframe', 34],
    '/resources/dummy.js': ['script', 7],
    '/resources/dummy.css': ['link', 8],
    '/svg/resources/greenSquare.svg': ['object', 244],
};

const srcFieldExceptions = {
    'object': 'data',
    'link': 'href',
};

const totalResourceCount = Object.keys(urls).length;
const cacheBuster = '?cb=' + Math.random().toString().substr(2);
const seen = {};
let seenResourceCount = 0;
let t = async_test('PerformanceResourceTiming sizes tags test');

function addTag(url, tag) {
    const element = document.createElement(tag);
    let srcfield = srcFieldExceptions[tag];
    if (!srcfield) {
        srcfield = 'src';
    }
    element.setAttribute(srcfield, url + cacheBuster);
    element.setAttribute('class', 'invisible');
    if (tag === 'link') {
        element.setAttribute('rel', 'stylesheet');
    }
    document.body.appendChild(element);
}

// Postpone checking until everything is loaded so that the checks will be done
// in a deterministic order.
function loaded(list) {
    for (const entry of list.getEntries()) {
        const url = new URL(entry.name);
        if (urls[url.pathname]) {
            seen[url.pathname] = {
                expectedSize: urls[url.pathname][1],
                entry
            };
            ++seenResourceCount;
        }
    }
    if (seenResourceCount === totalResourceCount) {
        checkAllResources();
    }
}

function checkAllResources() {
    for (const relativeUrl of Object.keys(urls).sort()) {
        checkResourceSizes(relativeUrl);
    }
    removeTags();
    t.done();
}

function removeTags() {
    let els = document.getElementsByClassName('invisible');
    while (els.length) {
        document.body.removeChild(els[0]);
    }
}

function checkResourceSizes(relativeUrl) {
    const { expectedSize, entry }  = seen[relativeUrl];
    decodedBodySize = entry.decodedBodySize;
    assert_equals(entry.decodedBodySize, expectedSize,
                  relativeUrl + ' decodedBodySize');
    assert_equals(entry.encodedBodySize, expectedSize,
                  relativeUrl + ' encodedBodySize');
    transferSize = entry.transferSize;
    assert_greater_than(entry.transferSize, expectedSize,
                       relativeUrl + ' transferSize');
}

function runTest() {
    let observer = new PerformanceObserver(loaded);
    observer.observe({entryTypes: ["resource"]});
    for (const url in urls) {
        addTag(url, urls[url][0]);
    }
}

window.onload = t.step_func(runTest);
</script>
